#include "ALOPSNR.h"

CALOPSNR::CALOPSNR()
{
}

CALOPSNR::CALOPSNR(CALStepItem* pStepItem)
{
	m_pStepItem = pStepItem;
}

CALOPSNR::~CALOPSNR()
{
}


void CALOPSNR::test()
{
	//Mat I1 = imread("swan1.jpg", 1);           // Read the two images
	//Mat I2 = imread("swan2.jpg", 1);

	////BufferPSNR bufferPSNR;
	////BufferMSSIM bufferMSSIM;

	//int TIMES;
	//stringstream sstr("500");
	//sstr >> TIMES;
	//double time, result;

	////------------------------------- PSNR CPU ----------------------------------------------------
	//time = (double)getTickCount();

	//for (int i = 0; i < TIMES; ++i)
	//	result = getPSNR(I1, I2);

	//time = 1000 * ((double)getTickCount() - time) / getTickFrequency();
	//time /= TIMES;

	//cout << "Time of PSNR CPU (averaged for " << TIMES << " runs): " << time << " milliseconds."
	//	<< " With result of: " << result << endl;
}

void CALOPSNR::convert()
{
	if (m_pStepItem == NULL) return;

	try
	{
		CALSIOPSNR* pStepItem = (CALSIOPSNR*)m_pStepItem;

		int nNum = pStepItem->GetItemNum();

		//------------------------------- PSNR CPU ----------------------------------------------------
		double result;

		//for (int i = 0; i < nNum; ++i)
			result = getPSNR(m_srcMat, m_srcMat1);

		MapString info;
		info.strName = "PSNR(CPU)";
		info.strValue = convertToString(result);

		m_desInfoList.push_back(info);

		SetDstType(AL_DST_Info);
	}
	catch (...)
	{

	}
}

void CALOPSNR::convert(const Mat &src, Mat &dst)
{

}

double CALOPSNR::getPSNR(const Mat& I1, const Mat& I2)
{
	Mat s1;
	absdiff(I1, I2, s1);       // |I1 - I2|
	s1.convertTo(s1, CV_32F);  // cannot make a square on 8 bits
	s1 = s1.mul(s1);           // |I1 - I2|^2

	Scalar s = sum(s1);         // sum elements per channel

	double sse = s.val[0] + s.val[1] + s.val[2]; // sum channels

	if (sse <= 1e-10) // for small values return zero
		return 0;
	else
	{
		double  mse = sse / (double)(I1.channels() * I1.total());
		double psnr = 10.0*log10((255 * 255) / mse);
		return psnr;
	}
}


//double CALOPSNR::getPSNR_GPU_optimized(const Mat& I1, const Mat& I2, BufferPSNR& b)
//{
//	b.gI1.upload(I1);
//	b.gI2.upload(I2);
//
//	b.gI1.convertTo(b.t1, CV_32F);
//	b.gI2.convertTo(b.t2, CV_32F);
//
//	gpu::absdiff(b.t1.reshape(1), b.t2.reshape(1), b.gs);
//	gpu::multiply(b.gs, b.gs, b.gs);
//
//	double sse = gpu::sum(b.gs, b.buf)[0];
//
//	if (sse <= 1e-10) // for small values return zero
//		return 0;
//	else
//	{
//		double mse = sse / (double)(I1.channels() * I1.total());
//		double psnr = 10.0*log10((255 * 255) / mse);
//		return psnr;
//	}
//}


//
//double CALOPSNR::getPSNR_GPU(const Mat& I1, const Mat& I2)
//{
//	gpu::GpuMat gI1, gI2, gs, t1, t2;
//
//	gI1.upload(I1);
//	gI2.upload(I2);
//
//	gI1.convertTo(t1, CV_32F);
//	gI2.convertTo(t2, CV_32F);
//
//	gpu::absdiff(t1.reshape(1), t2.reshape(1), gs);
//	gpu::multiply(gs, gs, gs);
//
//	Scalar s = gpu::sum(gs);
//	double sse = s.val[0] + s.val[1] + s.val[2];
//
//	if (sse <= 1e-10) // for small values return zero
//		return 0;
//	else
//	{
//		double  mse = sse / (double)(gI1.channels() * I1.total());
//		double psnr = 10.0*log10((255 * 255) / mse);
//		return psnr;
//	}
//}